﻿using Godot;


public static class SpiralUtil
{
    /// <summary>
    /// 螺旋算法  顺时针
    /// 7   8  9  10
    /// 6   1  2
    /// 5   4  3
    /// </summary>
    private static float[][] SCREW_CLOCKWISE = new float[][] { new float[] { 1, 2, 3, 4 }, new float[] { 4, 1, 2, 3 } };

    /// <summary>
    /// 螺旋算法
    /// </summary>
    /// <param name="index">当前序列</param>
    /// <returns>返回当前序列应该所在的位置</returns>
    public static Vector2I Screw(int index)
    {
        //总体思路是先找到第几圈  然后再找到第几个拐角 然后用switch
        //因为一般序列都是从0开始的,所以此处加一以适应规则
        index++;
        //如果求的是中心点 直接返回就行了
        if (index <= 1) return new Vector2I(0, 0);

        //开平方得到当前序列在哪个阶段中(阶段=第几圈*2)
        var n = Mathf.Ceil(Mathf.Sqrt(index));
        var step = Mathf.FloorToInt(n / 2) * 2;
        //求出当前序列是当前阶段中的第几个数
        var stepIndex = index - (step - 1) * (step - 1);
        //求出当前序列在当前阶段中的第几条边上
        var stepStep = Mathf.CeilToInt((float)stepIndex / step);
        //当前序列是当前边上第几个数
        var ssi = stepIndex % step;
        if (ssi == 0) ssi = step;

        return new Vector2I(
            GetValue(step, ssi, SCREW_CLOCKWISE[0][stepStep - 1]),
            GetValue(step, ssi, SCREW_CLOCKWISE[1][stepStep - 1])
        );
    }

    private static int GetValue(int step, int ssi, float switchIndex)
    {
        switch (switchIndex)
        {
            case 1: return step / 2;
            case 2: return step / 2 - ssi;
            case 3: return -step / 2;
            case 4: return -step / 2 + ssi;
        }

        return 0;
    }
}
